package xutil

import (
	"fmt"
	"runtime"
)

// Errors of not found include redis/mongo/mysql
const (
	RedisNil           = "redis: nil"
	MongoNotFound      = "not found"
	MysqlNoRows        = "sql: no rows in result set"
	RPCRespNil         = "rpc: nil"
	XsqlErrNilRows     = "[scanner]: rows can't be nil"
	XsqlErrEmptyResult = `[scanner]: empty result`
)

// ContainStr check if string target in string array
func ContainStr(source []string, target string) bool {
	for _, elem := range source {
		if elem == target {
			return true
		}
	}
	return false
}

// ContainInt check if int target in int array
func ContainInt(source []int, target int) bool {
	for _, elem := range source {
		if elem == target {
			return true
		}
	}
	return false
}

// IsNotFound check if nil in redis/not found in mongo/no rows in mysql
// If sdk has change error msg, this will return wrong result, rarely
func IsNotFound(err error) bool {
	if err != nil {
		errMsg := err.Error()
		if errMsg == RedisNil ||
			errMsg == MongoNotFound ||
			errMsg == MysqlNoRows ||
			errMsg == XsqlErrNilRows ||
			errMsg == XsqlErrEmptyResult ||
			errMsg == RPCRespNil {
			return true
		}
		return false
	}
	return false
}

// SafeFuncWrapper 安全封装f函数，避免Panic导致全局退出
func SafeFuncWrapper(f func()) (err error) {
	defer func() {
		if msg := recover(); msg != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			err = fmt.Errorf("%v\n %s\n", msg, buf)
		}
	}()
	f()
	return
}
